package Game.GameStates 
{
	import Box2D.Collision.b2AABB;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2ContactListener;
	import Box2D.Dynamics.b2DebugDraw;
	import Box2D.Dynamics.b2World;
	import Box2D.Dynamics.Contacts.b2Contact;
	import Common.Animation;
	import Common.ContactListener;
	import Common.GamePhysics;
	import Common.Input;
	import Common.Managers.SwfManager;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.system.System;
	import flash.utils.getTimer;
	import Game.AI.EnemyTankAI;
	import Game.Effects.Explosion;
	import Game.GameCamera;
	import Game.GameElements.Background;
	import Game.GameElements.BattleTower;
	import Game.GameElements.GameObject;
	import Game.GameElements.Rocket;
	import Game.GameElements.Tank;
	import Game.GameElements.Wall;
	import Game.Online.Connection;
	import Game.Online.Messages.MessageKeyPress;
	import Game.Online.Messages.MessageCorrectPosition;
	import Game.Online.Messages.MessagesHandler;
	import Game.Online.OnlineManager;
	import Game.Windows.DebugWindow;
	import Game.Windows.LoadingWindow;
	import Game.Windows.MessageWindow;
	import Game.Windows.MiniMap;
	import Game.World;
	/**
	 * ...
	 * @author Yevgeniy Logachev
	 */
	public class GameState extends BaseState
	{
		private var m_currentLevel:int 						= 1;
		private var m_contactListener:ContactListener		= null;
		
		private var m_lastFrameTime: int = getTimer();
		private var m_lastKeyTime: int = getTimer();
		private var m_correctPosTime: int = getTimer();
						
		public function GameState(level:int = 1) 
		{
			super();
			m_currentLevel = level;
								
			m_contactListener = new ContactListener(onContact);
			GamePhysics.instance.physicalWorld.SetContactListener(m_contactListener);			
			// Show loading anim while resources is loading
			//LoadingWindow.show = true;
			// Load all resources
			SwfManager.instance.releaseAll();
			SwfManager.instance.loadAll([Tank.m_swfPath, Wall.m_swfPath, Background.m_swfPath, Rocket.m_swfPath, Explosion.m_swfPath, BattleTower.m_swfPath], onResourceLoaded);
			
			Main.mainSprite.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		}
				
		public function onResourceLoaded():void
		{
			LoadingWindow.show = false;

			World.instance.initialize(m_currentLevel, onInitWorld);
			
			if (Settings.enableOnline)
			{
				OnlineManager.instance.logIn();
			}
		}
		
		public function onInitWorld():void
		{
			if (!Settings.enableOnline)
			{
				// Test objects
				new Tank(150, 150, 0, 1, Tank.TYPE_AI_BOT, EnemyTankAI.HARD);
				new Tank(300, 300, 0, 1, Tank.TYPE_AI_BOT, EnemyTankAI.HARD);
				new Tank(500, 150, Tank.TYPE_AI_BOT, 1, EnemyTankAI.HARD);
				new Tank(600, 122, 0, 1, Tank.TYPE_GAME_PLAYER);
				new BattleTower(1150, 150, 30);
			}
			
			MiniMap.show = true;
			
			GamePhysics.instance.debugDraw();
									
			m_isInit = true;
		}
		
		public function onServerConnect(e:Event):void
		{
			m_isInit = true;
		}
		
		public function onServerError(e:Event):void
		{
			m_isInit = false;
		}
				
		override public function update():void
		{		
			if (Tank.getGamePlayer() != null && getTimer() - m_lastKeyTime > 150)
			{
				m_lastKeyTime = getTimer();
				
				var msg:MessageKeyPress = null;
				
				if (Input.isKeyDown(Input.KEY_RIGHT))
				{
					Tank.getGamePlayer().moveTo(Tank.DIRECTION_RIGHT);
					if (Settings.enableOnline)
					{
						msg = new MessageKeyPress();
						msg.setData(Input.KEY_RIGHT);
					}
				}
				else if (Input.isKeyDown(Input.KEY_LEFT))
				{
					Tank.getGamePlayer().moveTo(Tank.DIRECTION_LEFT);
					if (Settings.enableOnline)
					{
						msg = new MessageKeyPress();
						msg.setData(Input.KEY_LEFT);
					}
				}
				else if (Input.isKeyDown(Input.KEY_DOWN))
				{
					Tank.getGamePlayer().moveTo(Tank.DIRECTION_DOWN);
					if (Settings.enableOnline)
					{	
						msg = new MessageKeyPress();
						msg.setData(Input.KEY_DOWN);
					}
				}
				else if (Input.isKeyDown(Input.KEY_UP))
				{
					Tank.getGamePlayer().moveTo(Tank.DIRECTION_UP);
					if (Settings.enableOnline)
					{	
						msg = new MessageKeyPress();
						msg.setData(Input.KEY_UP);
					}
				}
				else
				{
					Tank.getGamePlayer().idle();
				}
												
				if (Input.isKeyDown(Input.KEY_SPACE))
				{
					Tank.getGamePlayer().doRocket();
					if (Settings.enableOnline)
					{
						msg = new MessageKeyPress();
						msg.setData(Input.KEY_SPACE);
					}
				}
				
				if (msg != null && Settings.enableOnline)
				{
					MessagesHandler.instance.addMessage(msg);
					OnlineManager.instance.connection.sendMessage(msg);
				}
			}
			
			if (getTimer() - m_correctPosTime > 300 && Settings.enableOnline)
			{
				m_correctPosTime = getTimer();
				
				var msgMove:MessageCorrectPosition = new MessageCorrectPosition();
				msgMove.setData(Tank.getGamePlayer().physicalObject.GetPosition().x, Tank.getGamePlayer().physicalObject.GetPosition().y, Tank.getGamePlayer().getDirection + 1);
				MessagesHandler.instance.addMessage(msgMove);
				OnlineManager.instance.connection.sendMessage(msgMove);
			}			
			
			for each(var object:GameObject in GameObject.gameObjects)
			{
				object.update();
			}			
			MiniMap.update();
			
			const curFrameTime : int    = getTimer();
            const dt           : Number = 0.001 * (curFrameTime - m_lastFrameTime);
            m_lastFrameTime = curFrameTime;
			GamePhysics.instance.physicalWorld.Step(1.0/60.0, 10, 10);
			GamePhysics.instance.physicalWorld.ClearForces();
			if (Settings.enableDebugData)
			{
				GamePhysics.instance.physicalWorld.DrawDebugData();
			}
			
			// Update screen object to be equal physical object     
			for(var body:b2Body = GamePhysics.instance.physicalWorld.GetBodyList(); body; body = body.GetNext())
			{
				if (!(body.GetUserData() is DisplayObject))
				{
					continue;
				}
				
				body.GetUserData().x = int(body.GetPosition().x * GamePhysics.instance.physicalScale);
				body.GetUserData().y = int(body.GetPosition().y * GamePhysics.instance.physicalScale);
				
				body.GetUserData().rotation = body.GetAngle() * (180.0 / Math.PI);
			}
			
			if (Tank.getGamePlayer() != null)
			{
				//if (Tank.getGamePlayer().physicalObject.GetLinearVelocity().x != 0 || Tank.getGamePlayer().physicalObject.GetLinearVelocity().y != 0)
				{
					GameCamera.instance.scroll(Tank.getGamePlayer().x, Tank.getGamePlayer().y);
				}
			}
		}
		
		private function onContact(point:b2Contact):void
		{
			var bodyA:b2Body = point.GetFixtureA().GetBody();
			var bodyB:b2Body = point.GetFixtureB().GetBody();
			
			var object1:* = bodyA.GetUserData();
			var object2:* = bodyB.GetUserData();
			
			if (object1 is Rocket && (object1 as Rocket).m_owner != object2)
			{
				(object1 as GameObject).doDestroy();
				(object2 as GameObject).doDestroy();
			}
		}
		
		public function onKeyDown(e:KeyboardEvent):void
		{
			trace("Key code: " + e.keyCode);
			if (e.keyCode == 66)
			{
				
			}
			if (e.keyCode == 78)
			{
				
			}
			if (e.keyCode == Input.KEY_ESC)
			{
				DebugWindow.instance.show = !DebugWindow.instance.show;
			}
			if (e.keyCode == Input.KEY_P)
			{
				var str:String = "Mem: " + Math.round(System.totalMemory / (1024 * 1024)) + " MB";
				DebugWindow.instance.addLine(str);
			}
		}
	}
}